package com.yaorange.certificate.service.impl;

import java.util.List;
import java.util.concurrent.*;

import com.yaorange.certificate.bo.NjtLoginUserVo;
import com.yaorange.certificate.bo.RegisterVo;
import com.yaorange.certificate.utils.SmsUtils;
import com.yaorange.common.constant.HttpStatus;
import com.yaorange.common.core.domain.entity.SysUser;
import com.yaorange.common.core.domain.model.LoginUser;
import com.yaorange.common.exception.ServiceException;
import com.yaorange.common.utils.DateUtils;
import com.yaorange.common.utils.SecurityUtils;
import com.yaorange.common.utils.StringUtils;
import com.yaorange.common.utils.nongjt.ValidateCodeUtils;
import com.yaorange.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.yaorange.certificate.mapper.NjtUserRegisterMapper;
import com.yaorange.certificate.domain.NjtUserRegister;
import com.yaorange.certificate.service.INjtUserRegisterService;
import org.springframework.transaction.annotation.Transactional;

//import javax.net.ssl.KeyManager;
//import javax.net.ssl.X509TrustManager;
import java.util.*;

/**
 * 用户注册信息Service业务层处理
 *
 * @author loong
 * @date 2025-01-14
 */
@Service
@Slf4j
public class NjtUserRegisterServiceImpl implements INjtUserRegisterService
{
    public static final String NONGJT_REGISTER_KEY = "nongjt:register.";
    public static final String NONGJT_CODE_KEY = "nongjt:code.";
    @Autowired
    private NjtUserRegisterMapper njtUserRegisterMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SmsUtils sendSms;
    //定一个异步线程池,用于1秒后异步发送验证码
    private static final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ISysUserService sysUserService;

    /**
     * 查询用户注册信息
     *
     * @param id 用户注册信息主键
     * @return 用户注册信息
     */
    @Override
    public NjtUserRegister selectNjtUserRegisterById(Long id)
    {
        return njtUserRegisterMapper.selectNjtUserRegisterById(id);
    }

    /**
     * 查询用户注册信息列表
     *
     * @param njtUserRegister 用户注册信息
     * @return 用户注册信息
     */
    @Override
    public List<NjtUserRegister> selectNjtUserRegisterList(NjtUserRegister njtUserRegister)
    {
        return njtUserRegisterMapper.selectNjtUserRegisterList(njtUserRegister);
    }

    /**
     * 新增用户注册信息
     *
     * @param njtUserRegister 用户注册信息
     * @return 结果
     */
    @Override
    public int insertNjtUserRegister(NjtUserRegister njtUserRegister)
    {
        njtUserRegister.setCreateTime(DateUtils.getNowDate());
        return njtUserRegisterMapper.insertNjtUserRegister(njtUserRegister);
    }

    /**
     * 修改用户注册信息
     *
     * @param njtUserRegister 用户注册信息
     * @return 结果
     */
    @Override
    public int updateNjtUserRegister(NjtUserRegister njtUserRegister)
    {
        njtUserRegister.setUpdateTime(DateUtils.getNowDate());
        return njtUserRegisterMapper.updateNjtUserRegister(njtUserRegister);
    }

    /**
     * 批量删除用户注册信息
     *
     * @param ids 需要删除的用户注册信息主键
     * @return 结果
     */
    @Override
    public int deleteNjtUserRegisterByIds(Long[] ids)
    {
        return njtUserRegisterMapper.deleteNjtUserRegisterByIds(ids);
    }

    /**
     * 删除用户注册信息信息
     *
     * @param id 用户注册信息主键
     * @return 结果
     */
    @Override
    public int deleteNjtUserRegisterById(Long id)
    {
        return njtUserRegisterMapper.deleteNjtUserRegisterById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class,readOnly = true)
    public void sendValidateCode(String mobilePhone) {
        //判断该手机号是否已经发送过(1分钟内)
        String limitKey = NONGJT_REGISTER_KEY + mobilePhone;
        Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent(limitKey, "1", 60, TimeUnit.SECONDS);
        if (Boolean.FALSE.equals(ifAbsent)) {
            //给浏览器响应400状态码，表示请求失败
            throw new ServiceException("验证码已发送，请稍后再试", HttpStatus.TOO_MANY_REQUESTS);
        }

        //查询注册表,判断该手机号是否已经注册过
        NjtUserRegister userRegister = njtUserRegisterMapper.selectNjtUserRegisterByMobilePhone(mobilePhone);
        if (userRegister != null) {
            //给浏览器响应400状态码，表示请求失败
            throw new ServiceException("该手机号已经注册过", HttpStatus.BAD_REQUEST);
        }

        //生成一个6位数的验证码
        String code = ValidateCodeUtils.generateValidateCode(6);
        String codeKey = NONGJT_CODE_KEY + mobilePhone;
        //保存到redis(string类型,key:nongjt:code.手机号   value:验证码   过期时间 300秒)
        redisTemplate.opsForValue().set(codeKey, code, 300, TimeUnit.SECONDS);

        log.debug("正在给:[{}]发送验证码:[{}]", mobilePhone, code);
        //发送短信验证码
//        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
//        scheduledExecutorService.schedule(()->{
//            sendSms.sendSms(mobilePhone, code);
//        }, 1, TimeUnit.SECONDS);
    }

    @Override
    @Transactional(readOnly = true)
    public Boolean checkMobilePhone(String mobilePhone) {
        NjtUserRegister userRegister = njtUserRegisterMapper.selectNjtUserRegisterByMobilePhone(mobilePhone);
        if(ObjectUtils.isNotEmpty(userRegister)){
            throw new ServiceException("手机号已经注册过了");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterVo registerVo) {
        try {
            //1. 校验验证码是否正确
            String mobilePhone = registerVo.getMobilePhone();
            String codeKey = NONGJT_CODE_KEY + mobilePhone;
            String redisCode = stringRedisTemplate.opsForValue().get(codeKey);
            if (StringUtils.isEmpty(redisCode)) {
                throw new ServiceException("该手机号还没有发送过验证码");
            }
            String clientCode = registerVo.getCheckCode();
            if (!clientCode.equals(redisCode)) {
                throw new ServiceException("验证码不正确");
            }
            //2. 判断手机号是否存在
            NjtUserRegister userRegister = njtUserRegisterMapper.selectNjtUserRegisterByMobilePhone(mobilePhone);
            if (userRegister != null) {
                throw new ServiceException("该手机号已经被注册");
            }
            //3. 插入系统用户表(ruoyi)
            SysUser sysUser = new SysUser();
            sysUser.setUserName(mobilePhone);
            sysUser.setUserType("02");
            //spring security密码加密器加密
            String encryptPassword = SecurityUtils.encryptPassword(registerVo.getPassword());
            sysUser.setPassword(encryptPassword);

            sysUserService.registerUser(sysUser);
            Long userId = sysUser.getUserId();

            //4. 插入用户注册表(nongjt)
            userRegister = new NjtUserRegister();
            //维护和系统用户表之间的关系(公用主键)
            userRegister.setId(userId);
            userRegister.setRegisterTime(new Date());
            userRegister.setUserStatus(0L);
            userRegister.setDelFlag(0L);
            userRegister.setMemberFlag(0L);
            userRegister.setMemberFlag(0L);
            userRegister.setMobilePhone(mobilePhone);
            userRegister.setCreateBy(mobilePhone);
            userRegister.setCreateTime(userRegister.getUpdateTime());

            njtUserRegisterMapper.insertNjtUserRegister(userRegister);
            //4. 清理redis中的验证码
            stringRedisTemplate.delete(codeKey);
        } catch (ServiceException e) {
            log.error("注册失败", e);
            throw new ServiceException("注册失败");
        }
    }

    @Override
    @Transactional(readOnly = true)
    public NjtLoginUserVo queryLoginUser() {
        //获取到用户基本信息userId
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserId();

        //查询用户注册信息
        NjtUserRegister userRegister = njtUserRegisterMapper.selectNjtUserRegisterById(userId);
        NjtLoginUserVo njtLoginUserVo = new NjtLoginUserVo();
        njtLoginUserVo.setUserRegister(userRegister);
        njtLoginUserVo.setSysUser(loginUser);
        return njtLoginUserVo;
    }
}
